//! HTTP API数据源
//! 
//! 提供基于HTTP API的数据查询功能

use std::collections::HashMap;
use async_trait::async_trait;
use serde_json::{Value, json};
use reqwest::Client;

use crate::{DataSource, DataSourceQuery, DataSourceResult, DataSourceStats};

/// HTTP API数据源
pub struct HttpApiDataSource {
    name: String,
    description: String,
    connected: bool,
    base_url: String,
    client: Client,
    headers: HashMap<String, String>,
}

impl HttpApiDataSource {
    /// 创建新的HTTP API数据源
    pub fn new(base_url: String) -> Self {
        Self {
            name: "HTTP API数据源".to_string(),
            description: "基于HTTP API的数据查询，支持REST API调用".to_string(),
            connected: false,
            base_url,
            client: Client::new(),
            headers: HashMap::new(),
        }
    }
    
    /// 设置请求头
    pub fn set_header(&mut self, key: String, value: String) {
        self.headers.insert(key, value);
    }
    
    /// 设置认证头
    pub fn set_auth_header(&mut self, token: String) {
        self.headers.insert("Authorization".to_string(), format!("Bearer {}", token));
    }
    
    /// 执行HTTP GET请求
    async fn execute_get(&self, path: &str) -> anyhow::Result<Value> {
        let url = if path.starts_with("http") {
            path.to_string()
        } else {
            format!("{}/{}", self.base_url.trim_end_matches('/'), path.trim_start_matches('/'))
        };
        
        let mut request = self.client.get(&url);
        
        // 添加请求头
        for (key, value) in &self.headers {
            request = request.header(key, value);
        }
        
        let response = request.send().await?;
        let status = response.status();
        let text = response.text().await?;
        
        if status.is_success() {
            // 尝试解析为JSON
            match serde_json::from_str::<Value>(&text) {
                Ok(json_value) => Ok(json!({
                    "status": status.as_u16(),
                    "data": json_value,
                    "content_type": "application/json"
                })),
                Err(_) => Ok(json!({
                    "status": status.as_u16(),
                    "data": text,
                    "content_type": "text/plain"
                }))
            }
        } else {
            Err(anyhow::anyhow!("HTTP请求失败: {} - {}", status, text))
        }
    }
    
    /// 执行HTTP POST请求
    async fn execute_post(&self, path: &str, body: &Value) -> anyhow::Result<Value> {
        let url = if path.starts_with("http") {
            path.to_string()
        } else {
            format!("{}/{}", self.base_url.trim_end_matches('/'), path.trim_start_matches('/'))
        };
        
        let mut request = self.client.post(&url).json(body);
        
        // 添加请求头
        for (key, value) in &self.headers {
            request = request.header(key, value);
        }
        
        let response = request.send().await?;
        let status = response.status();
        let text = response.text().await?;
        
        if status.is_success() {
            // 尝试解析为JSON
            match serde_json::from_str::<Value>(&text) {
                Ok(json_value) => Ok(json!({
                    "status": status.as_u16(),
                    "data": json_value,
                    "content_type": "application/json"
                })),
                Err(_) => Ok(json!({
                    "status": status.as_u16(),
                    "data": text,
                    "content_type": "text/plain"
                }))
            }
        } else {
            Err(anyhow::anyhow!("HTTP请求失败: {} - {}", status, text))
        }
    }
    
    /// 执行HTTP查询
    async fn execute_http_query(&self, query: &str, parameters: &HashMap<String, Value>) -> anyhow::Result<Value> {
        let query = query.trim();
        
        if query.starts_with("GET ") {
            let path = query.strip_prefix("GET ").unwrap().trim();
            self.execute_get(path).await
        } else if query.starts_with("POST ") {
            let parts: Vec<&str> = query.strip_prefix("POST ").unwrap().splitn(2, ' ').collect();
            if parts.len() == 2 {
                let path = parts[0];
                let body_str = parts[1];
                
                // 尝试解析请求体
                let body = if body_str.starts_with('{') {
                    serde_json::from_str(body_str)?
                } else {
                    // 使用参数作为请求体
                    json!(parameters)
                };
                
                self.execute_post(path, &body).await
            } else {
                let path = parts[0];
                self.execute_post(path, &json!(parameters)).await
            }
        } else if query.starts_with("http://") || query.starts_with("https://") {
            // 直接URL请求
            self.execute_get(query).await
        } else {
            Err(anyhow::anyhow!("不支持的HTTP查询格式: {}", query))
        }
    }
}

#[async_trait]
impl DataSource for HttpApiDataSource {
    fn name(&self) -> &str {
        &self.name
    }
    
    fn description(&self) -> &str {
        &self.description
    }
    
    async fn connect(&mut self) -> anyhow::Result<()> {
        tracing::info!("连接到HTTP API数据源: {}", self.base_url);
        
        // 尝试连接到基础URL进行健康检查
        match self.client.get(&self.base_url).send().await {
            Ok(_) => {
                self.connected = true;
                Ok(())
            }
            Err(e) => {
                tracing::warn!("HTTP API连接测试失败，但仍标记为已连接: {}", e);
                // 即使连接测试失败，也标记为已连接，因为API可能不支持根路径访问
                self.connected = true;
                Ok(())
            }
        }
    }
    
    async fn disconnect(&mut self) -> anyhow::Result<()> {
        tracing::info!("断开HTTP API数据源连接");
        self.connected = false;
        Ok(())
    }
    
    async fn is_connected(&self) -> bool {
        self.connected
    }
    
    async fn execute_query(&mut self, query: DataSourceQuery) -> anyhow::Result<DataSourceResult> {
        if !self.connected {
            return Err(anyhow::anyhow!("数据源未连接"));
        }
        
        let start_time = std::time::Instant::now();
        
        tracing::debug!("执行HTTP API查询: {}", query.content);
        
        match self.execute_http_query(&query.content, &query.parameters).await {
            Ok(data) => {
                let duration = start_time.elapsed();
                let rows_processed = 1; // HTTP请求通常返回一个响应
                
                Ok(DataSourceResult {
                    success: true,
                    data,
                    error: None,
                    stats: DataSourceStats {
                        execution_time_ms: duration.as_millis() as f64,
                        rows_processed,
                        bytes_processed: query.content.len() as u64,
                    },
                })
            }
            Err(e) => {
                let duration = start_time.elapsed();
                Ok(DataSourceResult {
                    success: false,
                    data: json!({}),
                    error: Some(e.to_string()),
                    stats: DataSourceStats {
                        execution_time_ms: duration.as_millis() as f64,
                        rows_processed: 0,
                        bytes_processed: query.content.len() as u64,
                    },
                })
            }
        }
    }
    
    async fn health_check(&self) -> anyhow::Result<Value> {
        let api_accessible = match self.client.get(&self.base_url).send().await {
            Ok(response) => response.status().is_success(),
            Err(_) => false,
        };
        
        Ok(json!({
            "status": if self.connected { "connected" } else { "disconnected" },
            "name": self.name,
            "base_url": self.base_url,
            "api_accessible": api_accessible,
            "headers_count": self.headers.len()
        }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_http_api_data_source() {
        // 使用一个公共的测试API
        let mut source = HttpApiDataSource::new("https://httpbin.org".to_string());
        
        // 测试连接
        assert!(!source.is_connected().await);
        source.connect().await.unwrap();
        assert!(source.is_connected().await);
        
        // 测试GET查询
        let query = DataSourceQuery {
            id: "test".to_string(),
            content: "GET /json".to_string(),
            parameters: HashMap::new(),
        };
        
        let result = source.execute_query(query).await.unwrap();
        // 注意：这个测试可能因为网络问题而失败，在实际环境中应该使用mock
        if result.success {
            assert!(result.stats.execution_time_ms > 0.0);
        }
        
        // 测试健康检查
        let health = source.health_check().await.unwrap();
        assert_eq!(health["status"], "connected");
        
        // 测试断开连接
        source.disconnect().await.unwrap();
        assert!(!source.is_connected().await);
    }
    
    #[tokio::test]
    async fn test_http_api_with_headers() {
        let mut source = HttpApiDataSource::new("https://httpbin.org".to_string());
        
        // 设置请求头
        source.set_header("User-Agent".to_string(), "DataGateway/1.0".to_string());
        source.set_auth_header("test-token".to_string());
        
        source.connect().await.unwrap();
        
        // 测试带请求头的查询
        let query = DataSourceQuery {
            id: "test".to_string(),
            content: "GET /headers".to_string(),
            parameters: HashMap::new(),
        };
        
        let result = source.execute_query(query).await.unwrap();
        // 这个测试也可能因为网络问题而失败
        if result.success {
            assert!(result.stats.execution_time_ms > 0.0);
        }
    }
}
